package org.zhangyp.n01jdkapi.n04thread;
/**
 * @Title: 模拟哲学家吃饭的问题  死锁问题
 * 在每个循环中，哲学家首先会开始思考，思考一段时间之后（这个时间长度可以是随机的），
 * 他感到饿了，就准备开始吃饭。在吃饭之前必须先拿到左手的筷子，再拿到右手的筷子，
 * 然后才开始吃饭；吃完之后，先放回右手的筷子，再放回左手的筷子；由于这是个 while 循环，
 * 所以他就会继续思考人生，开启下一个循环。
 * @Description: TODO
 * @Params:
 * @return
 * @throws
 * @Author: Vector
 * @DateTime:
 */
public class DiningPhilosophers {

    public static class Philosopher implements Runnable {

        private Object leftChopstick;
        private Object rightChopstick;

        public Philosopher(Object leftChopstick, Object rightChopstick) {
            this.leftChopstick = leftChopstick;
            this.rightChopstick = rightChopstick;
        }

        @Override
        public void run() {
            try {
                doAction("思考人生、宇宙、万物、灵魂...");
                synchronized (leftChopstick) {
                    doAction("拿起左边的筷子");
                    synchronized (rightChopstick) {
                        doAction("拿起右边的筷子");
                        doAction("吃饭");
                        doAction("放下右边的筷子");
                    }
                    doAction("放下左边的筷子");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        private void doAction(String action) throws InterruptedException {
            System.out.println(Thread.currentThread().getName() + " " + action);
            Thread.sleep((long) (Math.random() * 10));
        }
    }

    public static void main(String[] args) {
        Philosopher[] philosophers = new Philosopher[5];
        Object[] chopsticks = new Object[philosophers.length];
        for (int i = 0; i < chopsticks.length; i++) {
            chopsticks[i] = new Object();
        }
        for (int i = 0; i < philosophers.length; i++) {
            Object leftChopstick = chopsticks[i];
            Object rightChopstick = chopsticks[(i + 1) % chopsticks.length];
            philosophers[i] = new Philosopher(rightChopstick, leftChopstick);
            new Thread(philosophers[i], "哲学家" + (i + 1) + "号").start();
        }
    }
}
